import 'dart:io';
import 'dart:isolate';
import 'package:get/get.dart';
import 'package:uuid/uuid.dart';
import 'package:path/path.dart' as path;

import '../../models/upload_task.dart';
import '../../models/file_metadata.dart';
import '../database_service.dart';
import '../tianyi_cloud_service.dart';
import '../notification_service.dart';
import '../file_manager_service.dart';
import '../preferences_service.dart';

class UploadService extends GetxService {
  final DatabaseService _databaseService = Get.find<DatabaseService>();
  final TianyiCloudService _cloudService = Get.find<TianyiCloudService>();
  final NotificationService _notificationService = Get.find<NotificationService>();
  final FileManagerService _fileManagerService = Get.find<FileManagerService>();
  final PreferencesService _preferencesService = Get.find<PreferencesService>();
  
  // 上传任务列表
  final RxList<UploadTask> _uploadTasks = <UploadTask>[].obs;
  List<UploadTask> get uploadTasks => _uploadTasks;
  
  // 正在上传的任务
  final RxList<UploadTask> _activeUploads = <UploadTask>[].obs;
  List<UploadTask> get activeUploads => _activeUploads;
  
  // 上传队列
  final List<UploadTask> _uploadQueue = [];
  
  // 上传统计
  final RxInt _totalTasks = 0.obs;
  final RxInt _completedTasks = 0.obs;
  final RxInt _failedTasks = 0.obs;
  final RxDouble _totalProgress = 0.0.obs;
  
  int get totalTasks => _totalTasks.value;
  int get completedTasks => _completedTasks.value;
  int get failedTasks => _failedTasks.value;
  double get totalProgress => _totalProgress.value;
  
  @override
  Future<void> onInit() async {
    super.onInit();
    await _loadUploadTasks();
    _startUploadProcessor();
  }
  
  // 加载上传任务
  Future<void> _loadUploadTasks() async {
    final tasks = await _databaseService.getAllUploadTasks();
    _uploadTasks.value = tasks;
    _updateStatistics();
    
    // 恢复未完成的上传任务
    final pendingTasks = tasks.where((task) => 
      task.status == UploadStatus.pending || 
      task.status == UploadStatus.paused
    ).toList();
    
    _uploadQueue.addAll(pendingTasks);
  }
  
  // 开始上传处理器
  void _startUploadProcessor() {
    // 定期处理上传队列
    Stream.periodic(const Duration(seconds: 1)).listen((_) {
      _processUploadQueue();
    });
  }
  
  // 处理上传队列
  Future<void> _processUploadQueue() async {
    final maxConcurrent = _preferencesService.getMaxUploadConcurrent();
    
    while (_activeUploads.length < maxConcurrent && _uploadQueue.isNotEmpty) {
      final task = _uploadQueue.removeAt(0);
      await _startUpload(task);
    }
  }
  
  // 添加上传任务
  Future<UploadTask> addUploadTask(
    File file,
    String targetPath, {
    String? customFileName,
  }) async {
    final fileName = customFileName ?? path.basename(file.path);
    final fileSize = await file.length();
    final md5 = await TianyiCloudService.calculateFileMd5(file);
    
    final task = UploadTask(
      id: const Uuid().v4(),
      fileName: fileName,
      filePath: file.path,
      fileSize: fileSize,
      md5: md5,
      mimeType: _fileManagerService.getMimeType(fileName),
      targetPath: targetPath,
      createdTime: DateTime.now(),
    );
    
    await _databaseService.insertUploadTask(task);
    _uploadTasks.add(task);
    _uploadQueue.add(task);
    _updateStatistics();
    
    return task;
  }
  
  // 批量添加上传任务
  Future<List<UploadTask>> addMultipleUploadTasks(
    List<File> files,
    String targetPath,
  ) async {
    final tasks = <UploadTask>[];
    
    for (final file in files) {
      final task = await addUploadTask(file, targetPath);
      tasks.add(task);
    }
    
    return tasks;
  }
  
  // 开始上传
  Future<void> _startUpload(UploadTask task) async {
    try {
      // 更新任务状态
      final updatedTask = task.copyWith(
        status: UploadStatus.uploading,
        startTime: DateTime.now(),
      );
      await _updateTask(updatedTask);
      _activeUploads.add(updatedTask);
      
      // 显示上传开始通知
      if (_preferencesService.getUploadNotification()) {
        await _notificationService.showUploadStartNotification(task.fileName);
      }
      
      // 检查文件是否已存在（秒传）
      final existingFile = await _cloudService.checkFileExists(task.md5, task.fileSize);
      if (existingFile != null) {
        await _handleRapidUpload(updatedTask, existingFile);
        return;
      }
      
      // 获取上传URL
      final uploadInfo = await _cloudService.getUploadUrl(
        task.fileName,
        task.md5,
        task.fileSize,
        '0', // 根目录ID，实际应该根据targetPath获取
      );
      
      // 更新任务信息
      final taskWithUploadInfo = updatedTask.copyWith(
        uploadUrl: uploadInfo['uploadUrl'],
        uploadParams: uploadInfo['uploadParams'],
      );
      await _updateTask(taskWithUploadInfo);
      
      // 开始文件上传
      await _uploadFile(taskWithUploadInfo);
      
    } catch (e) {
      await _handleUploadError(task, e.toString());
    }
  }
  
  // 处理秒传
  Future<void> _handleRapidUpload(UploadTask task, Map<String, dynamic> existingFile) async {
    try {
      // 保存文件元数据
      final metadata = FileMetadata(
        md5: task.md5,
        fileName: task.fileName,
        fileSize: task.fileSize,
        mimeType: task.mimeType,
        cloudId: existingFile['fileId'],
        createdTime: DateTime.now(),
        updatedTime: DateTime.now(),
      );
      await _databaseService.insertFileMetadata(metadata);
      
      // 添加到虚拟文件系统
      await _fileManagerService.addFileToVirtualSystem(
        task.fileName,
        task.md5,
        task.targetPath,
      );
      
      // 更新任务状态
      final completedTask = task.copyWith(
        status: UploadStatus.completed,
        progress: 100.0,
        uploadedBytes: task.fileSize,
        completedTime: DateTime.now(),
        cloudId: existingFile['fileId'],
      );
      
      await _updateTask(completedTask);
      _activeUploads.removeWhere((t) => t.id == task.id);
      
      // 显示完成通知
      if (_preferencesService.getUploadNotification()) {
        await _notificationService.showUploadCompleteNotification(task.fileName);
      }
      
    } catch (e) {
      await _handleUploadError(task, '秒传失败: $e');
    }
  }
  
  // 上传文件
  Future<void> _uploadFile(UploadTask task) async {
    try {
      final file = File(task.filePath);
      
      await _cloudService.uploadFile(
        task.uploadUrl!,
        file,
        task.uploadParams!,
        onProgress: (sent, total) async {
          final progress = (sent / total * 100).clamp(0.0, 100.0);
          
          final updatedTask = task.copyWith(
            uploadedBytes: sent,
            progress: progress,
          );
          
          await _updateTask(updatedTask);
          
          // 更新进度通知
          if (_preferencesService.getUploadNotification()) {
            await _notificationService.showUploadProgressNotification(
              task.fileName,
              sent,
              total,
            );
          }
        },
      );
      
      // 上传完成
      await _handleUploadComplete(task);
      
    } catch (e) {
      await _handleUploadError(task, e.toString());
    }
  }
  
  // 处理上传完成
  Future<void> _handleUploadComplete(UploadTask task) async {
    try {
      // 保存文件元数据
      final metadata = FileMetadata(
        md5: task.md5,
        fileName: task.fileName,
        fileSize: task.fileSize,
        mimeType: task.mimeType,
        cloudId: task.cloudId,
        createdTime: DateTime.now(),
        updatedTime: DateTime.now(),
      );
      await _databaseService.insertFileMetadata(metadata);
      
      // 添加到虚拟文件系统
      await _fileManagerService.addFileToVirtualSystem(
        task.fileName,
        task.md5,
        task.targetPath,
      );
      
      // 更新任务状态
      final completedTask = task.copyWith(
        status: UploadStatus.completed,
        progress: 100.0,
        uploadedBytes: task.fileSize,
        completedTime: DateTime.now(),
      );
      
      await _updateTask(completedTask);
      _activeUploads.removeWhere((t) => t.id == task.id);
      
      // 显示完成通知
      if (_preferencesService.getUploadNotification()) {
        await _notificationService.showUploadCompleteNotification(task.fileName);
      }
      
    } catch (e) {
      await _handleUploadError(task, '完成处理失败: $e');
    }
  }
  
  // 处理上传错误
  Future<void> _handleUploadError(UploadTask task, String error) async {
    final failedTask = task.copyWith(
      status: UploadStatus.failed,
      errorMessage: error,
    );
    
    await _updateTask(failedTask);
    _activeUploads.removeWhere((t) => t.id == task.id);
    
    // 显示错误通知
    if (_preferencesService.getUploadNotification()) {
      await _notificationService.showUploadFailedNotification(task.fileName, error);
    }
  }
  
  // 暂停上传
  Future<void> pauseUpload(String taskId) async {
    final task = _uploadTasks.firstWhereOrNull((t) => t.id == taskId);
    if (task != null && task.isUploading) {
      final pausedTask = task.copyWith(status: UploadStatus.paused);
      await _updateTask(pausedTask);
      _activeUploads.removeWhere((t) => t.id == taskId);
    }
  }
  
  // 恢复上传
  Future<void> resumeUpload(String taskId) async {
    final task = _uploadTasks.firstWhereOrNull((t) => t.id == taskId);
    if (task != null && task.isPaused) {
      final resumedTask = task.copyWith(status: UploadStatus.pending);
      await _updateTask(resumedTask);
      _uploadQueue.add(resumedTask);
    }
  }
  
  // 取消上传
  Future<void> cancelUpload(String taskId) async {
    final task = _uploadTasks.firstWhereOrNull((t) => t.id == taskId);
    if (task != null) {
      final cancelledTask = task.copyWith(status: UploadStatus.cancelled);
      await _updateTask(cancelledTask);
      _activeUploads.removeWhere((t) => t.id == taskId);
      _uploadQueue.removeWhere((t) => t.id == taskId);
    }
  }
  
  // 删除上传任务
  Future<void> deleteUploadTask(String taskId) async {
    await _databaseService.deleteUploadTask(taskId);
    _uploadTasks.removeWhere((t) => t.id == taskId);
    _activeUploads.removeWhere((t) => t.id == taskId);
    _uploadQueue.removeWhere((t) => t.id == taskId);
    _updateStatistics();
  }
  
  // 清除已完成的任务
  Future<void> clearCompletedTasks() async {
    final completedTasks = _uploadTasks.where((t) => t.isCompleted).toList();
    for (final task in completedTasks) {
      await deleteUploadTask(task.id);
    }
  }
  
  // 重试失败的任务
  Future<void> retryFailedTask(String taskId) async {
    final task = _uploadTasks.firstWhereOrNull((t) => t.id == taskId);
    if (task != null && task.isFailed) {
      final retryTask = task.copyWith(
        status: UploadStatus.pending,
        errorMessage: null,
        uploadedBytes: 0,
        progress: 0.0,
        startTime: null,
        completedTime: null,
      );
      await _updateTask(retryTask);
      _uploadQueue.add(retryTask);
    }
  }
  
  // 更新任务
  Future<void> _updateTask(UploadTask task) async {
    await _databaseService.updateUploadTask(task);
    final index = _uploadTasks.indexWhere((t) => t.id == task.id);
    if (index != -1) {
      _uploadTasks[index] = task;
    }
    
    // 更新活跃上传列表
    final activeIndex = _activeUploads.indexWhere((t) => t.id == task.id);
    if (activeIndex != -1) {
      _activeUploads[activeIndex] = task;
    }
    
    _updateStatistics();
  }
  
  // 更新统计信息
  void _updateStatistics() {
    _totalTasks.value = _uploadTasks.length;
    _completedTasks.value = _uploadTasks.where((t) => t.isCompleted).length;
    _failedTasks.value = _uploadTasks.where((t) => t.isFailed).length;
    
    if (_uploadTasks.isNotEmpty) {
      final totalProgress = _uploadTasks.fold<double>(
        0.0,
        (sum, task) => sum + task.progress,
      );
      _totalProgress.value = totalProgress / _uploadTasks.length;
    } else {
      _totalProgress.value = 0.0;
    }
  }
  
  // 获取上传速度
  double getUploadSpeed() {
    if (_activeUploads.isEmpty) return 0.0;
    
    return _activeUploads.fold<double>(
      0.0,
      (sum, task) => sum + task.uploadSpeed,
    );
  }
  
  // 获取剩余时间估算
  Duration? getEstimatedTimeRemaining() {
    final speed = getUploadSpeed();
    if (speed <= 0) return null;
    
    final remainingBytes = _uploadTasks
        .where((t) => !t.isCompleted && !t.isFailed && !t.isCancelled)
        .fold<int>(0, (sum, task) => sum + (task.fileSize - task.uploadedBytes));
    
    if (remainingBytes <= 0) return null;
    
    final remainingSeconds = remainingBytes / speed;
    return Duration(seconds: remainingSeconds.round());
  }
}